package com.dushuren.project.controller;
import java.util.Date;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.dushuren.project.common.BaseResponse;
import com.dushuren.project.common.ErrorCode;
import com.dushuren.project.common.ResultUtils;
import com.dushuren.project.exception.BusinessException;
import com.dushuren.project.mapper.TeamApplyMapper;
import com.dushuren.project.mapper.TeamMapper;
import com.dushuren.project.mapper.UserTeamMapper;
import com.dushuren.project.model.dto.*;
import com.dushuren.project.model.entity.Team;
import com.dushuren.project.model.entity.TeamApply;
import com.dushuren.project.model.entity.User;
import com.dushuren.project.model.entity.UserTeam;
import com.dushuren.project.model.vo.TeamApplyVo;
import com.dushuren.project.model.vo.UserVo;
import com.dushuren.project.service.TeamApplyService;
import com.dushuren.project.service.UserService;
import com.dushuren.project.service.UserTeamService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.dushuren.project.constant.TeamApplyConstant.*;
import static com.dushuren.project.constant.UserConstant.USER_JOIN_CREDITS;

@RestController
@RequestMapping("/apply")
@Slf4j
public class TeamApplyController {

  @Resource
  TeamApplyService teamApplyService;

  @Resource
  UserService userService;

  @Resource
  TeamApplyMapper teamApplyMapper;


  @Resource
  UserTeamMapper userTeamMapper;

  @Resource
  UserTeamService userTeamService;

  @Resource
  private RedissonClient redissonClient;

  @Resource
  TeamMapper teamMapper;

  /***
   * 申请加入队伍
   * @param applyJoinTeamRequest
   * @param request
   * @return
   */
  @PostMapping("/join/team")
  public BaseResponse<Long> applyJoinTeam(@RequestBody ApplyJoinTeamRequest applyJoinTeamRequest, HttpServletRequest request) {
	User loginUser = userService.getLoginUser(request);
	if (loginUser.getCreditsNum() < USER_JOIN_CREDITS) {
	  throw new BusinessException(ErrorCode.NO_AUTH, "信用值过低");
	}
	Long userId = applyJoinTeamRequest.getUserId();
	if (!userId.equals(loginUser.getId())) {
	  throw new BusinessException(ErrorCode.PARAMS_ERROR);
	}

	// 校验申请者是否为队长
	Long teamId = applyJoinTeamRequest.getTeamId();
	if (Boolean.TRUE.equals(teamApplyService.checkCapatinTeam(teamId, userId))) {
	  throw new BusinessException(ErrorCode.PARAMS_ERROR, "不能申请自己创建的队伍");
	}
	// 校验申请加入队伍者不能重复进行申请加入队伍
	if (Boolean.TRUE.equals(teamApplyService.checkApplyTeam(teamId, userId))) {
	  throw new BusinessException(ErrorCode.PARAMS_ERROR, "不能重复申请该队伍");
	}
	// 只有一个线程能获取到锁
	RLock rLock = redissonClient.getLock("dushuren:apply_join_team:lock");
	try{
	  int number = 0;
	  // 抢倒锁并执行
	  while (true) {
		number++;
		if (rLock.tryLock(0, -1, TimeUnit.MILLISECONDS)) {
		  System.out.println("Lock" + Thread.currentThread().getId());
		  teamApplyService.applyJoinTeam(applyJoinTeamRequest);
		  return ResultUtils.success(0L);
		}
		// 避免出现线程堆积，出现死锁
		if (number >= 3) {
		  return ResultUtils.success(1L);
		}
	  }
	}catch (InterruptedException e){
	  log.error("doCacheRecommendUser", e);
	  return ResultUtils.success(1L);
	}finally {
	  // 只能释放自己的锁
	  if (rLock.isHeldByCurrentThread()) {
		System.out.println("unLock" + Thread.currentThread().getId());
		rLock.unlock();
	  }
	}
  }


  /***
   * 删除申请
   * @param applyDeleteTeamRequest
   * @param request
   * @return
   */
  @PostMapping("/delete/Team")
  public BaseResponse<Long> applyDeleteTeam(@RequestBody ApplyDeleteTeamRequest applyDeleteTeamRequest, HttpServletRequest request) {
	User loginUser = userService.getLoginUser(request);
	if (!applyDeleteTeamRequest.getUserId().equals(loginUser.getId()) || applyDeleteTeamRequest.getUserId() == null || applyDeleteTeamRequest.getId() == null) {
	  throw new BusinessException(ErrorCode.PARAMS_ERROR);
	}
	teamApplyService.applyDeleteTeam(applyDeleteTeamRequest);
	return ResultUtils.success(0L);
  }

  /***
   * 查看所有申请列表 - 管理员
   */
  @GetMapping("/list/team")
  public BaseResponse<List<TeamApplyVo>> listQueryApplyTeam(ApplyListQueryTeamRequest listQueryTeamRequest, HttpServletRequest request) {
	userService.isAdministrators(request);
	if (StringUtils.isAllEmpty(listQueryTeamRequest.getApplyContent(), listQueryTeamRequest.getApplyReviewMessage()) &&
	  (listQueryTeamRequest.getTeamId() == null && listQueryTeamRequest.getId() == null && listQueryTeamRequest.getApplyReviewStatus() == null)) {
	  QueryWrapper<TeamApply> queryWrapper = new QueryWrapper<>();
	  queryWrapper.select("id", "teamId", "userId", "applyContent", "applyReviewStatus", "applyReviewMessage", "createTime");
	  List<TeamApplyVo> teamApplyVos = teamApplyMapper.selectList(queryWrapper).stream().map(teamApply -> {
		TeamApplyVo teamApplyVo = new TeamApplyVo();
		BeanUtils.copyProperties(teamApply, teamApplyVo);
		return teamApplyVo;
	  }).collect(Collectors.toList());
	  return ResultUtils.success(teamApplyVos);
	}
	List<TeamApplyVo> resultApplyTeam = teamApplyService.listQueryApplyTeam(listQueryTeamRequest);
	if (CollectionUtils.isEmpty(resultApplyTeam)) {
	  throw new BusinessException(ErrorCode.PARAMS_ERROR);
	}
	return ResultUtils.success(resultApplyTeam);
  }


  /***
   * 个人查看申请列表 公开信息的申请列表
   */
  @GetMapping("/Get/Team")
  public BaseResponse<List<TeamApplyVo>> getApplyTeam(ApplyGetTeamRequest applyGetTeamRequest, HttpServletRequest request) {
	UserVo userVO = userService.getIsServletRequest(request);
	Long userId = applyGetTeamRequest.getUserId();
	if (!userVO.getId().equals(userId)) {
	  throw new BusinessException(ErrorCode.PARAMS_ERROR);
	}
	QueryWrapper<TeamApply> queryWrapper = new QueryWrapper<>();
	queryWrapper.eq("userId",userId);
	queryWrapper.select("id", "teamId", "userId", "applyContent", "applyReviewStatus", "applyReviewMessage", "createTime");
	if (applyGetTeamRequest.getApplyReviewStatus() == null || !applyGetTeamRequest.getApplyReviewStatus().equals(TEAM_APPLY_STATE_IN)) {
	  //	  queryWrapper.and(qw -> qw.eq("applyReviewStatus",TEAM_APPLY_STATE_ADOPT).or().eq("applyReviewStatus", TEAM_APPLY_STATE_REFUSE));
	  queryWrapper.in("applyReviewStatus", Arrays.asList(TEAM_APPLY_STATE_ADOPT,TEAM_APPLY_STATE_REFUSE));
	} else {
	  queryWrapper.eq("applyReviewStatus", TEAM_APPLY_STATE_IN);
	}
	List<TeamApplyVo> teamApplyVos = teamApplyMapper.selectList(queryWrapper).stream().map(teamApply -> {
	  TeamApplyVo teamApplyVo = new TeamApplyVo();
	  BeanUtils.copyProperties(teamApply, teamApplyVo);
	  return teamApplyVo;
	}).collect(Collectors.toList());
	return ResultUtils.success(teamApplyVos);
  }


  /***
   * 队长查看申请列表
   */
  @GetMapping("/capatin/Team")
  public BaseResponse<List<TeamApplyVo>> captainGetApplyTeam(ApplyCaptainGetTeamRequest captainGetTeamRequest, HttpServletRequest request) {
	UserVo isServletRequest = userService.getIsServletRequest(request);
	if (!captainGetTeamRequest.getUserId().equals(isServletRequest.getId())) {
	  throw new BusinessException(ErrorCode.PARAMS_ERROR, "无权限");
	}
	List<TeamApplyVo> listResult = teamApplyService.captainGetApplyTeam(captainGetTeamRequest);

	return ResultUtils.success(listResult);
  }

  /***
   * 审核通过加入队伍申请
   */
  @PostMapping("/check/join/team")
  @Transactional(rollbackFor = Exception.class)
  public BaseResponse<Long> checkJoinApplyTeam(@RequestBody ApplyCheckJoinTeamRequest checkJoinTeamRequest, HttpServletRequest request) {
	UserVo userVO = userService.getIsServletRequest(request);
	Long teamId = checkJoinTeamRequest.getTeamId();
	// 校验是否为队伍队长
	if (Boolean.FALSE.equals(teamApplyService.checkCapatinTeam(teamId,userVO.getId()))) {
	  throw new BusinessException(ErrorCode.NO_AUTH);
	}
	// 校验申请者 已加入的队伍是否>= 5
	Long userId = checkJoinTeamRequest.getUserId();
	Long userTeamCount = userTeamService.QueryUserTeam(userId);
	// 当 userTeamCount = 4 时则，将甚于的申请全部拒绝
	// 校验当前 申请中的 id  是否存在

	Long id = checkJoinTeamRequest.getId();
	if (Boolean.TRUE.equals(teamApplyService.isApplyTeamId(id, TEAM_APPLY_STATE_IN))) {
	  throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前请求不存在");
	}
	// 当期为4时代表这个加入后队伍就满了
	if (userTeamCount == 4) {
	  try {
		// 删除所有队伍申请
		UpdateWrapper<Team> queryWrapperTeam = new UpdateWrapper<>();
		queryWrapperTeam.eq("userId",userId);
		queryWrapperTeam.set("teamApplyState", 2);
		queryWrapperTeam.set("teamApplyMessage", "加入的队伍已满");
		teamMapper.update(null, queryWrapperTeam);
		// 删除所有加入队伍申请
		UpdateWrapper<TeamApply> updateWrapperTeamApply = new UpdateWrapper<>();
		updateWrapperTeamApply.eq("userId",userId);
		updateWrapperTeamApply.set("applyReviewStatus", 2);
		updateWrapperTeamApply.set("applyReviewMessage", "加入的队伍已满");
		teamApplyMapper.update(null, updateWrapperTeamApply);
	  } catch (Exception e) {
		throw new BusinessException(ErrorCode.NULL_ERROR, "并没有多余的申请");
	  }
	}
	UpdateWrapper<TeamApply> updateWrapper = new UpdateWrapper<>();
	updateWrapper.eq("id",id);
	updateWrapper.set("applyReviewStatus", TEAM_APPLY_STATE_ADOPT);
	// 修改为通过
	teamApplyMapper.update(null,updateWrapper);
	// 加入当前队伍
	UserTeam userTeam = new UserTeam();
	userTeam.setUserId(userId);
	userTeam.setTeamId(teamId);
	userTeam.setJoinTeam(new Date());
	userTeamService.save(userTeam);
	return ResultUtils.success(0L);
  }


  /***
   * 拒接队伍加入申请 CheckNoJoinApplyTeam
   */
  @PostMapping("/check/nojoin/team")
  public BaseResponse<Long> checkNoJoinApplyTeam(@RequestBody ApplyCheckNoJoinTeamRequest checkNoJoinTeamRequest, HttpServletRequest request) {
	UserVo userVO = userService.getIsServletRequest(request);
	// 校验当前这个人为队长
	// 校验是否为队伍队长
	Long teamId = checkNoJoinTeamRequest.getTeamId();
	Long id = checkNoJoinTeamRequest.getId();
	Long userId = checkNoJoinTeamRequest.getUserId();
	if (teamId == null || id == null || userId == null) {
	  throw new BusinessException(ErrorCode.NULL_ERROR);
	}
	if (Boolean.FALSE.equals(teamApplyService.checkCapatinTeam(teamId,userVO.getId()))) {
	  throw new BusinessException(ErrorCode.NO_AUTH);
	}
	// 校验当前申请是否存在
	if (Boolean.TRUE.equals(teamApplyService.isApplyTeamId(id, TEAM_APPLY_STATE_IN))) {
	  throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前请求不存在");
	}
	UpdateWrapper<TeamApply> updateWrapper = new UpdateWrapper<>();
	updateWrapper.eq("id",id);
	updateWrapper.eq("teamId", teamId);
	updateWrapper.eq("userId", userId);
	// 校验 拒绝信息是否存在
	String applyReviewMessage = checkNoJoinTeamRequest.getApplyReviewMessage();
	if (StringUtils.isNotBlank(applyReviewMessage)) {
	  updateWrapper.set("applyReviewMessage", applyReviewMessage);
	}
	updateWrapper.set("applyReviewStatus", TEAM_APPLY_STATE_REFUSE);
	teamApplyMapper.update(null, updateWrapper);
	return ResultUtils.success(0L);
  }


}
